package modules

import (
	"net"
	"time"
	"os"
	"bufio"
	"adai.design/homemaster/log"
	"encoding/json"
	"runtime"
	"io/ioutil"
	"os/exec"
)


type wifiConfig struct {
	Mode 		string		`json:"mode"`
	ApSsid 		string		`json:"ap_ssid"`
	ApPasswd 	string		`json:"ap_passwd"`
	StaSsid 	string		`json:"sta_ssid"`
	StaPasswd 	string		`json:"sta_passwd"`
	state 		bool
}

func (w *wifiConfig) save() error {
	data, err := json.Marshal(w)
	if err != nil {
		return err
	}

	var file string
	if runtime.GOARCH != "mipsle" {
		path := os.Getenv("GOPATH") + "/src/adai.design/homemaster/build/tmp/"
		file = path + "wifi.cfg"
	} else {
		file = "/etc/homemaster/wifi.cfg"
	}

	return ioutil.WriteFile(file, data, 0666)
}

var wifi = func() *wifiConfig {
	config := wifiConfig{
		Mode: "sta",
		ApSsid: "homemaster",
		ApPasswd: "howoldareyou",
		StaSsid: "#daodao",
		StaPasswd: "howoldareyou",
	}

	var file string
	if runtime.GOARCH != "mipsle" {
		path := os.Getenv("GOPATH") + "/src/adai.design/homemaster/build/tmp/"
		file = path + "wifi.cfg"
	} else {
		file = "/etc/homemaster/wifi.cfg"
	}

	data, err := ioutil.ReadFile(file)
	if err != nil {
		return &config
	}

	json.Unmarshal(data, &config)
	return &config
}()


func getInterfaceInfo(name string) (ip string, up bool) {
	inte, err := net.InterfaceByName(name)
	if err != nil {
		log.Error("%s", err)
	}

	addrs, _ := inte.Addrs()
	for _,address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.To4().String(), (inte.Flags&net.FlagUp)!=0
			}
		}
	}
	return "", false
}

func wifiState() {
	ip, up := getInterfaceInfo("apcli0")
	log.Error("apcli0  up(%v) ip(%s)", up, ip)
	if up == false {
		SetOledMode(OledModeWifiConnecting, "#daodao")
	} else {
		SetOledMode(OledModeTime, "#daodao")
	}
	wifi.state = up

	for {
		if wifi.Mode == "ap" {
			time.Sleep(time.Millisecond * 500)
			continue
		}

		ip, up := getInterfaceInfo("apcli0")
		var newState = false
		if ip != "" && up {
			newState = true
		}
		if newState != wifi.state {
			wifi.state = newState
			log.Error("apcli0  up(%v) ip(%s)", wifi.state, ip)
			if wifi.state == false {
				SetOledMode(OledModeWifiConnecting, "#daodao")
			} else {
				SetOledMode(OledModeTime, "#daodao")
			}
		}
		time.Sleep(time.Millisecond * 500)
	}
}

type btnEventDesc struct {
	Button 		string		`json:"button"`
	Action 	 	string 		`json:"action"`
	Second  	int 		`json:"seen"`
}


func buttonEvent() {
	for {
		f, err := os.OpenFile("/tmp/btn.fifo", os.O_RDONLY, os.ModeNamedPipe)
		if err != nil {
			log.Error("%s", err)
		}
		input := bufio.NewReader(f)
		str, err := input.ReadString('\n')
		if err != nil {
			log.Error("%s", err)
		} else {
			log.Info("input: %s", str)

			var event btnEventDesc
			err := json.Unmarshal([]byte(str), &event)
			if err == nil {

				if event.Button == "wps" && event.Action == "released" && event.Second < 2 {
					if wifi.Mode == "sta" {
						wifi.Mode = "ap"
						exec.Command("wifimode", "ap").Start()
						SetOledMode(OledModeQRCodeApInfo, "")
					} else {
						if wifi.StaSsid != "" {
							wifi.Mode = "sta"
							exec.Command("wifimode", "sta", wifi.StaSsid, wifi.StaPasswd).Start()
							wifi.state = false
							SetOledMode(OledModeWifiConnecting, wifi.StaSsid)
						}
					}
				}
			}

		}
		defer f.Close()
	}
}

func SetWifi(ssid, passwd string) error {
	log.Info("wifi set ssid(%s) password(%s)", ssid, passwd)
	wifi.Mode = "sta"
	wifi.StaSsid = ssid
	wifi.StaPasswd = passwd
	wifi.save()
	wifi.state = false
	exec.Command("wifimode", "sta", wifi.StaSsid, wifi.StaPasswd).Start()
	SetOledMode(OledModeWifiConnecting, wifi.StaSsid)
	return nil
}

func StartWifiManager() {
	if runtime.GOARCH == "mipsle" {
		go wifiState()
		go buttonEvent()
	}
}
